# 任何东西都可以放在列表里  []
# 逗号分隔值 [元素1,元素2,....]
# 用方括括号，括起来
# 可以是任何值，和一个值的组合：整数int，浮点float，布尔值boolean，None，字符串str，列表list，字典dict
# 但通常它们是相同的类型的：
# 如一组数字，文件名，设备名称、描述一个网络设备的属性的对象，行星名
# print(type([]))

# stuff = [42, 3.14, True, None, "Foo Bar", ['another', 'list'], {'a': 'Dictionary', 'language': 'Python'}]
# print(stuff)
# # 任何布局（写法）
# # 布局都是随意的，
# # 尾随逗号都是可选的。
# more_stuff = [
#     42,
#     3.14,
#     True,
#     None,
#     "Foo Bar",
#     ['another', 'list'],
#     {
#         'a': 'Dictionary',
#         'language': 'Python',
#     },
# ]
# print(more_stuff)

# Lists
# 获取单个元素：: [index]
# 获取子列表：[start:end]
# 创建该子列表的拷贝
# planets = ['水星Mercury', '金星Venus', '地球Earth', '火星Mars', '木星Jupiter', '土星Saturn']
#
# print(planets)  # ['水星Mercury', '金星Venus', '地球Earth', '火星Mars', '木星Jupiter', '土星Saturn']
# print(len(planets))  # 6 length
#
#
# print(planets[0])  # 水星Mercury
# print(type(planets[0]))  # <class 'str'>
# print(planets[3])  # 火星Mars
#
# print(planets[0:1])  # ['水星Mercury']
# print(type(planets[0:1]))  # <class 'list'>
# print(planets[0:2])  # ['水星Mercury', '金星Venus']
# print(planets[1:3])  # ['金星Venus', '地球Earth']
#
# print(planets[2:])  # ['地球Earth', '火星Mars', '木星Jupiter', '土星Saturn']
# print(planets[:3])  # ['水星Mercury', '金星Venus', '地球Earth']
#
# # 复制了一份
# print(id(planets))
# print(id(planets[:]))  # ['水星Mercury', '金星Venus', '地球Earth', '火星Mars', '木星Jupiter', '土星Saturn']

# # 列出带step步长的切片  [start:end:step]
# letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
#
# print(letters[::])  # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
# print(letters[::1])  # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
# print(letters[::2])  # ['a', 'c', 'e', 'g', 'i']
# print(letters[1::2])  # ['b', 'd', 'f', 'h', 'j']
# print(letters[2:8:2])  # ['c', 'e', 'g']
# print(letters[1:1000:3])  # ['b', 'e', 'h']

# # 修改列表
# fruits = ['apple', 'banana', 'peach', 'strawberry']
# print(fruits)  # ['apple', 'banana', 'peach', 'strawberry']
# fruits[0] = 'orange'
# print(fruits)  # ['orange', 'banana', 'peach', 'strawberry']
#
# fruits[1:3] = ['grape', 'kiwi']
# print(fruits)  # ['orange', 'grape', 'kiwi', 'strawberry']
#
# fruits[1:3] = ['mango']
# print(fruits)  # ['orange', 'mango', 'strawberry']
#
# fruits[1:2] = ["banana", "peach"]
# print(fruits)  # ['orange', 'banana', 'peach', 'strawberry']

# # 可以使用切片表示法同时更改多个元素。甚至可以在切片和替换中有不同数量的元素。这也将改变列表的长度
# fruits = ['orange', 'mango', 'strawberry']
#
# fruits[1:2] = ["banana", "peach"]
# print(fruits) # ['orange', 'banana', 'peach', 'strawberry']
# 使用步长进行修改
# numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
# print(numbers)   # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
#
# numbers[1::2] = [0, 0, 0, 0, 0, 0]
# print(numbers)   # [1, 0, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0]

# 列表分配和列表副本
# 内存中有一个列表和两个指向它的指针。
#
# x = ['apple', 'bob', 'cat', 'drone']
# y = x
# x[0] = 'qqrq'
# print(x)  # ['qqrq', 'bob', 'cat', 'drone']
# print(y)  # ['qqrq', 'bob', 'cat', 'drone']
#
# print(id(x), id(y))


# 如果你真的想做一个拷贝，那么最简单的方法是使用切片语法。

# x = ['apple', 'bob', 'cat', 'drone']
# y = x[:]
#
# x[0] = 'qqrq'
#
# print(x)  # ['qqrq', 'bob', 'cat', 'drone']
# print(y)  # ['apple', 'bob', 'cat', 'drone']
#
# print(id(x), id(y))
# 它创建一个浅拷贝。
# Shallow vs. Deep copy of lists
# x = ['apple', ['cat', 'dog'], 'banana']
# print(x)  # ['apple', ['cat', 'dog'], 'banana']
# print(x[0])  # apple
# print(x[1][0])  # cat
#
# y = x[:]
#
# x[0] = 'kiwi'
# x[1][0] = 'mouse'
#
# print(x)  # ['kiwi', ['mouse', 'dog'], 'banana']
# print(y)  # ['apple', ['mouse', 'dog'], 'banana']
# print(id(y))
# print(id(x))
# print(id(x[1]))
# print(id(y[1]))

#
# from copy import deepcopy
#
# x = ['apple', ['cat', 'dog'], 'banana']
# print(x)  # ['apple', ['cat', 'dog'], 'banana']
# print(x[0])  # apple
# print(x[1][0])  # cat
#
# y = deepcopy(x)
# x[0] = 'kiwi'
# x[1][0] = 'mouse'
#
# print(x)  # ['kiwi', ['mouse', 'dog'], 'banana']
# print(y)  # ['apple', ['cat', 'dog'], 'banana']
# print(id(x[1]))
# print(id(y[1]))

# join 方法 str  '连接符'.join(列表)

# fields = ['one', 'two and three', 'four', 'five']
#
# together = ':'.join(fields)
# print(together)  # one:two and three:four:five
#
# together = ' '.join(fields)
# print(together)  # one two and three four five
#
# mixed = ' -=<> '.join(fields)
# print(mixed)  # one -=<> two and three -=<> four -=<> five
#
# another = ''.join(fields)
# print(another)  # onetwo and threefourfive

# join list of numbers

# a = ["x", "2", "y"]
# b = ["x", 2, "y"]
# print(":".join(a))  # x:2:y
# print(":".join(b))  # x:2:y
# print ":".join(b) # TypeError: sequence item 1: expected string, int found
#
# # convert elements to string using map
# print(":".join(map(str, b)))  # x:2:y
# https://www.runoob.com/python/python-func-map.html
#
# # convert elements to string using list comprehension
# print(":".join(str(x) for x in b))  # x:2:y
# https://www.runoob.com/python3/python-comprehensions.html

# split  字符串.split('分隔符')
# print('x:2:y'.split(':'))
# 特殊情况：将字符串分割为字符：使用list（）函数。
# 分割使用多个分割器：则需要使用 re.split

# words = "ab:cd::ef".split(':')
# print(words)  # ['ab', 'cd', '', 'ef']
#
# # special case: split by spaces
# names = "foo bar baz".split()
# print(names)  # ['foo', 'bar', 'baz']
#
# # special case: split to characters
# chars = list("ab cd")
# print(chars)  # ['a', 'b', ' ', 'c', 'd']


# for loop 循环列表
#
# things = ['apple', 'banana', 'peach', 42]
# for var in things:
#     print(var, type(var))

# in list 列表
# 检查该值是否在列表中？
#
# words = ['apple', 'banana', 'peach', '42']
# print('apple' in words)
# if 'apple' in words:
#     print('found apple')
#
# if 'a' in words:
#     print('found a')
# else:
#     print('NOT found a')
#
# if 42 in words:
#     print('found 42')
# else:
#     print('NOT found 42')

# 列表中的元素在哪里，求index
# words = ['cat', 'dog', 'snake', 'camel']
# print(words.index('snake'))
#
# print(words.index('python'))  # 会报错

# # 改良版 我先判断你在不在，在的话，我才求你的索引
# words = ['cat', 'dog', 'snake', 'camel']
#
# name = 'snake'
# if name in words:
#     print(words.index(name))
#
# name = 'python'
# if name in words:
#     print(words.index(name))

# 插入insert

# words = ['apple', 'banana', 'cat']
# print(words)  # ['apple', 'banana', 'cat']
#
# words.insert(2, 'zebra')
# print(words)  # ['apple', 'banana', 'zebra', 'cat']
#
# words.insert(0, 'dog')
# print(words)  # ['dog', 'apple', 'banana', 'zebra', 'cat']
#
# # Instead of this, use append (下面介绍)
# words.insert(len(words), 'olifant')
# print(words)  # ['dog', 'apple', 'banana', 'zebra', 'cat', 'olifant']

# 追加 append
#
# names = ['Foo', 'Bar', 'Zorg', 'Bambi']
# print(names) # ['Foo', 'Bar', 'Zorg', 'Bambi']
#
# names.append('Qux')
# print(names) # ['Foo', 'Bar', 'Zorg', 'Bambi', 'Qux']
#
#
# names.append([1,2])
# print(names) # ['Foo', 'Bar', 'Zorg', 'Bambi', 'Qux']

# 删除 remove
# 通过元素自身
# 从由第一个元素的值指定的列表中删除第一个元素。 [1,2,3,1,1]
# 如果列表中没有这样的元素，则抛出异常
# names = ['Joe', 'Kim', 'Jane', 'Bob', 'Kim']
# print(names)  # ['Joe', 'Kim', 'Jane', 'Bob', 'Kim']
#
# # len_name = len(names)
# # print(len_name)
# # ss = names.append([1,2])
# # print(names.append([1,2]), 22)
# # print(names)
#
# # def func(name_list):
# #     print('执行了')
# #
# #     return None
# # name_list = ['wx', 'wyj']
# # ss = func(name_list)
# # print(ss)
#
#
# print(names.remove('Kim'))  # None
# print(names)  # ['Joe', 'Jane', 'Bob', 'Kim']
#
# print(names.remove('George'))  # 会报错
# # Traceback (most recent call last):
# #   File "C:\Users\shy\Desktop\learn_python\009_列表.py", line 292, in <module>
# #     print(names.remove('George'))
# # ValueError: list.remove(x): x not in list

# pop 弹出（删除）
# 通过索引 位置来删除
# planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter']
# print(planets)  # ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter']
#
# third = planets.pop(2)
# print(third)  # Earth
# print(planets)  # ['Mercury', 'Venus', 'Mars', 'Jupiter']
#
# last = planets.pop()  # 默认是弹出最后一个
# print(last)  # Jupiter
# print(planets)  # ['Mercury', 'Venus', 'Mars']
#
# # planets.pop(4) # IndexError: pop index out of range
#
# jupyter_landers = []
# jupyter_landers.pop() # IndexError: pop from empty list

# 删除列表中的第一个元素

# names = ['foo', 'bar', 'baz', 'moo']
#
# first = names.pop(0)
# print(first)  # foo
# print(names)  # ['bar', 'baz', 'moo']
#
# 按索引删除列表中的多个元素
# 要按元素的索引删除该元素，请使用切片语法：
#
# names = ['foo', 'bar', 'baz', 'moo', 'qux']
#
# names[2:4] = []
# print(names)   # ['foo', 'bar', 'qux']


# 使用列表作为一个队列使用
# 先进先出 First In First Out
#
# a_queue = []
# print(a_queue)
#
# a_queue.append('Moo')
# print(a_queue)
#
# a_queue.append('Bar')
# print(a_queue)
#
# first = a_queue.pop(0)
# print(first)
# print(a_queue)

# Queue using deque from collections
# 使用collections中的【双端队列】
# from collections import deque
#
# # items = deque([])
# items = deque(['foo', 'bar'])
#
# print(type(items))  # <type 'collections.deque'>
# print(items)  # deque(['foo', 'bar'])
#
# items.append('zorg')
# print(items)  # deque(['foo', 'bar', 'zorg'])
# print(len(items))  # 3
#
# items.append('zorg')
# print(items)  # deque(['foo', 'bar', 'zorg', 'zorg'])
#
# nxt = items.popleft()
# print(nxt)  # 'foo'
# print(items)  # deque(['bar', 'zorg', 'zorg'])
# #
# # r = items.pop()
# # print(r)  # 'foo'
# # print(items)  # deque(['bar', 'zorg', 'zorg'])
#
# print(len(items))  # 3
#
# if items:
#     print("The queue has items")
# else:
#     print("The queue is empty")

# https://docs.python.org/zh-cn/3/library/collections.html#collections.deque

# Fixed size queue
# # 固定长度的队列
# from collections import deque
#
# queue = deque([], maxlen=3)  # 创建了一个队列，空的，但是最大长度为3
# print(len(queue))  # 0
# print(queue.maxlen)  # 3
#
# queue.append("Foo")
# queue.append("Bar")
# queue.append("Baz")
# print(queue)  # deque(['Foo', 'Bar', 'Baz'], maxlen=3)
#
# queue.append("Zorg")  # Automatically removes the left-most (first) element
# print(queue)  # deque(['Bar', 'Baz', 'Zorg'], maxlen=3)

#
# List as a stack
# 列表作为栈 使用
# 先进后出，后进先出
# stack = []
#
# stack.append("Joe")
# print(stack)
# stack.append("Jane")
# print(stack)
# stack.append("Bob")
# print(stack)
#
# while stack:
#     name = stack.pop()  # 删除最后一个元素
#     print(name)
#     print(stack)

# temp = []
# if temp:
#     print('ok')
# temp2 = [1, 2]
# if temp2:
#     print('ok2')

# 排序 sort  默认是升序，即小的在前面，大的在后面，reverse=True,降序，大的在前面，小的在后面
# sort
# planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn']
# print(planets)  # ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn']
# # for word in planets:
# #     print(word[0], ord(word[0]))
# planets.sort()
# print(planets)  # ['Earth', 'Jupiter', 'Mars', 'Mercury', 'Saturn', 'Venus']
# #
# planets.sort(reverse=True)
# print(planets)  # ['Venus', 'Saturn', 'Mercury', 'Mars', 'Jupiter', 'Earth']

#
# numbers = [7, 2, -4, 19, 8]
# print(numbers)  # [7, 2, -4, 19, 8]
# numbers.sort()
# print(numbers)  # [-4, 2, 7, 8, 19]
#
# numbers.sort(reverse=True)
# print(numbers)  # [19, 9, 7, 2, -4]
#
# numbers.sort(key=abs, reverse=True)  # 先对每个数进行取绝对值，然后按照降序进行排序
# print(numbers)  # [19, 9, 7, -4, 2]


# key sort
# 另一个使用key的例子。
# 要根据长度对列表进行排序
#
# animals = ['chicken', 'cow', 'snail', 'elephant']
# print(animals)
#
# animals.sort()  # 按照ascii值进行升序排序
# print(animals)
#
# animals.sort(key=len)  # [7, 3, 5, 8]
# print(animals)
#
# animals.sort(key=len, reverse=True)
# print(animals)

# sort with sorted
# animals = ['chicken', 'cow', 'snail', 'elephant']
# print(animals)  # ['chicken', 'cow', 'snail', 'elephant']
#
# s = sorted(animals)
# print(s)  # ['chicken', 'cow', 'elephant', 'snail']
# print(animals)  # ['chicken', 'cow', 'snail', 'elephant']
#
# # animal是需要排序的东西，reverse为true代表要降序，key表示按照什么方式进行排序
# r = sorted(animals, reverse=True, key=len)
# print(r)  # ['elephant', 'chicken', 'snail', 'cow']
# print(animals)  # ['chicken', 'cow', 'snail', 'elephant']

# 类  class 课程 抽象出来的  人类
# 对象 object 东西 一个实例  王鑫是一个人类的示例


# sort vs. sorted
# The sort() method will sort a list in-place（原位置） and return None 并且返回值是一个None.
# The built-in sorted() function will return the sorted list and leave the original list intact.

# key sort with sorted
# # 使用sorted排序的方法根据长度对列表进行排序
# animals = ['snail', 'cow', 'elephant', 'chicken']
# animals_in_abc = sorted(animals)
#
# print(animals)
# print(animals_in_abc)
#
# animals_by_length = sorted(animals, key=len)
# print(animals_by_length)

# letters = 'axzb'
# print(letters)  # 'axzb'
# s = sorted(letters)
# print(s)  # ['a', 'b', 'x', 'z']
# print(letters)  # 'axzb'
#
# r = ''.join(sorted(letters))
# print(r)  # abxz

# # range(start, end, step)
# for i in range(11, 18, 2):
#     print(i)
# 11
# 13
# 15
# 17
#
# # range(start,end)  # 默认步长step=1
# for i in range(5, 7):
#     print(i)
# # 5
# # 6
#
# # range(end)  # 默认的start是0，step=1
# for i in range(3):
#     print(i)
# # 0
# # 1
# # 2

# Looping over index 通过索引进行循环{遍历}

# things = ['abc', 'def', 'ghi', 42]
# for var in things:
#     print(var)
#
# things = ['abc', 'def', 'ghi', 42]
# for i in range(len(things)):  # len得到长度为4，range(4) [0,1,2,3]
#     print(i, things[i])

# Enumerate lists
# planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn']
# for idx, planet in enumerate(planets):
#     print(idx, planet)
#
# print('')
# enu = enumerate(planet)
# print(enu.__class__.__name__)
# print(enu)

# List operators
# 列表 运算
# a = ['one', 'two']
# b = ['three']
#
# print(a)  # ['one', 'two']
# # 类似字符串，重复几次
# print(a * 2)  # ['one', 'two', 'one', 'two']
# print(2 * a)  # ['one', 'two', 'one', 'two']
#
# print(a + b)  # ['one', 'two', 'three']
# print(b + a)  # ['three', 'one', 'two']

# List of lists
#
# x = ['abc', 'def']
# print(x)  # ['abc', 'def']
#
# y = [x, 'xyz']
# print(y)  # [['abc', 'def'], 'xyz']
# print(y[0])  # ['abc', 'def']
#
# print(x[0])  # abc
# print(y[0][0])  # abc

# List assignment
# x, y = 1, 2
# print(x)  # 1
# print(y)  # 2
#
# x, y = y, x  # 值交换了
# print(x)  # 2
# print(y)  # 1

# x = 44
# y = 55
# temp = x
# x = y
# y = temp
#
# print(x, y)

# tuple  元组
# 元组
# 元组是一个固定长度的不可变列表。它不能改变其大小或值。
# 一个元组用圆括号表示：(1,2,3)
# t = ('a', 'b', 'c')
# print(t)  # ('a', 'b', 'c')
# print(type(t))  # ('a', 'b', 'c')
# t[1] = 2

# List
# 列表中的元素可以通过其索引或列表切片符号进行更改。
# 一个列表可以使用append和pop方法或使用切片符号来增加或删除元素。
# 一个列表用方括号表示： [1,2,3]
# my_list = [1,2,3]
# my_list[0] = 44
# print(my_list)

#
# l = ['abc', 'def', 'qqrq']
# t = tuple(l)
# print(l)  # ['abc', 'def', 'qqrq']
# print(t)  # ('abc', 'def', 'qqrq')
# ll = list(t)
# print(ll)
# tuple很少使用。在某些地方，Python或某些模块需要元组（而不是列表）或返回一个元组（而不是列表）
# ，在每个地方都会被解释。否则，您就不需要使用元组了
# 例如，字典的键可以是元组（但不是列表）
# Sort tuples
# Sorting tuples or list, or other complex structures

students = [
    ('John', 'A', 2),
    ('Zoro', 'C', 1),
    ('Dave', 'B', 3),
]
print(students)
# [('John', 'A', 2), ('Zoro', 'C', 1), ('Dave', 'B', 3)]

print(sorted(students))


# [('Dave', 'B', 3), ('John', 'A', 2), ('Zoro', 'C', 1)]
# sort by the first element of each tuple

def my_sort(s):
    return s[1]


print('11')
print(sorted(students, key=lambda s: s[1]))
print(sorted(students, key=my_sort))
print('222')
# [('John', 'A', 2), ('Dave', 'B', 3), ('Zoro', 'C', 1)]
# sort by the 2nd element of the tuples (index 1)

print(sorted(students, key=lambda s: s[2]))
# [('Zoro', 'C', 1), ('John', 'A', 2), ('Dave', 'B', 3)]
# sort by the 3rd element of the tuples (index 2)


from operator import itemgetter

print(sorted(students, key=itemgetter(2)))
# [('Zoro', 'C', 1), ('John', 'A', 2), ('Dave', 'B', 3)]
# maybe this is more simple than the lambda version
# and probably faster
# my_lambda = lambda x: x ** 3
#
# def my_func(x):
#     return x**3
#
# print(my_lambda(2))
# print(my_func(2))

# Using a lambda expression, we can make this more compact
# 在使用lambda表达式时，可以使代码更加简洁